/*
 * @Author: xiaosihan
 * @Date: 2021-05-07 00:20:05
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2021-10-25 21:58:13
 */

import _ from "lodash";
import * as THREE from "three";
import { Camera, Line, LineSegments, MathUtils, MeshBasicMaterial, MeshStandardMaterial, PointsMaterial, Scene, WebGLRenderer } from "three";
import { Line2 } from "three/examples/jsm/lines/Line2.js";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2.js";
import { FullScreenQuad, Pass } from "three/examples/jsm/postprocessing/Pass.js";
import { CopyShader } from "three/examples/jsm/shaders/CopyShader.js";
import { Points } from "three/src/objects/Points.js";
import THREEInstancedMesh, { THREEInstancedMeshItem } from "../InstancedMesh/THREEInstancedMesh";
import Object3D from "./Object3D";

//辉光渲染对象
export default class GlowPass extends Pass {

    constructor(scene: THREE.Scene, camera: THREE.Camera, object3d: Object3D) {
        super();
        this.scene = scene; // 场景对象
        this.camera = camera; // 相机对象
        this.object3d = object3d; // 选中的object3d 对象
        this.uuid = MathUtils.generateUUID();
    }

    uuid!: string;

    scene!: Scene;
    camera!: Camera;
    object3d!: Object3D;

    glow_visibleColor?: string = "#04fa12"; //------可见区域辉光颜色
    glow_hiddenColor?: string = "#ff0000"; //-------不可见区域辉光颜色
    glow_depthTest: boolean = false; //--------深度测试 = false 时 不进行遮挡计算
    glow_opacity: number = 1; //---------------辉光透明度
    glow_fill: boolean = false; //--------------辉光填充整个模型区域
    glow_blurWidth: number = 10; //----------------辉光厚度
    glow_pulsePeriod: number = 0; //---------------辉光闪烁间隔时间_单位秒

    static cameraPos = new THREE.Vector3(); // 相机的世界坐标
    static currentMeshPos = new THREE.Vector3(); // 被挡住模型的世界坐标
    static targetMeshPos = new THREE.Vector3(); // 遮挡模型的模型世界坐标
    static triangle = new THREE.Triangle(); // 一个三角形用于计算面积对象

    // 计算 beMesh 有没有被 blockedMesh 遮挡住  返回 true 和 false
    static isBlocked(camera: { matrixWorld: THREE.Matrix4; }, beMesh: { geometry: { boundingSphere: { center: THREE.Vector3; radius: any; }; }; matrixWorld: THREE.Matrix4; }, blockedMesh: { geometry: { boundingSphere: { center: THREE.Vector3; radius: any; }; }; matrixWorld: THREE.Matrix4; }) {

        // 判断2个模型有没有尺寸
        if (
            beMesh.geometry.boundingSphere &&
            blockedMesh.geometry.boundingSphere
        ) {

            GlowPass.cameraPos.setFromMatrixPosition(camera.matrixWorld); // 获取相机对象的世界坐标
            GlowPass.currentMeshPos.setFromMatrixPosition(beMesh.matrixWorld).add(beMesh.geometry.boundingSphere.center); // 获取相机对象的世界坐标
            GlowPass.targetMeshPos.setFromMatrixPosition(blockedMesh.matrixWorld).add(blockedMesh.geometry.boundingSphere.center); // 获取相机对象的世界坐标

            let distance = GlowPass.cameraPos.distanceTo(GlowPass.currentMeshPos); // 获取相机与被遮挡模型的距离

            let radiusTatol = beMesh.geometry.boundingSphere.radius + blockedMesh.geometry.boundingSphere.radius; // 计算2个模型半径总和

            if (
                radiusTatol > GlowPass.targetMeshPos.distanceTo(GlowPass.cameraPos) || // 离相机太近了 就会挡住
                radiusTatol > GlowPass.targetMeshPos.distanceTo(GlowPass.currentMeshPos) // 离被遮挡的模型太近了 也会 挡住
            ) {
                return true; // 挡住了
            }

            // 设置三角形的3个点
            GlowPass.triangle.a.copy(GlowPass.cameraPos);
            GlowPass.triangle.b.copy(GlowPass.currentMeshPos);
            GlowPass.triangle.c.copy(GlowPass.targetMeshPos);

            if (
                distance > GlowPass.targetMeshPos.distanceTo(GlowPass.cameraPos) &&
                distance > GlowPass.targetMeshPos.distanceTo(GlowPass.currentMeshPos) &&
                GlowPass.triangle.getArea() < distance * radiusTatol * 0.5
            ) {
                return true; // 挡住了
            } else {
                return false; // 没有挡住
            }

        } else {
            return false; // 没有挡住
        }

    }

    // 创建一个渲染工具 用于处理纹理
    static fsQuad = new FullScreenQuad(); // 渲染辅助器

    // 全部对象的纹理
    static baseTextureTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });

    // 选中对象的纹理
    static selectTextureTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });

    // 比对对象的纹理
    static diffTextureTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });

    // 由于不能同时读写自己的纹理 
    static blur1TextureTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });

    // 所以需要用2个模糊纹理相互读写
    static blur2TextureTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });

    // 透明通道纹理
    static alphaMapTextureTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });

    // 透明通道着色器
    static alphaMapShader = new THREE.RawShaderMaterial({
        uniforms: {
            map: { value: null },
            hasMap: { value: false },
            alphaTest: { value: 0 },
            alphaMap: { value: null },
            hasAlphaMap: { value: false },
            opacity: { value: 0 }
        },
        vertexShader: `
            attribute vec3 position;
            attribute vec2 uv;
            varying vec2 vUv;
            void main() {
                vUv = uv;
                gl_Position = vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            #ifdef GL_ES
                precision highp float;
            #endif
            uniform sampler2D map;
            uniform bool hasMap;
            uniform sampler2D alphaMap;
            uniform bool hasAlphaMap;
            uniform float opacity;
            uniform float alphaTest;
            varying vec2 vUv;

            void main() {
                vec4 mapColor = texture2D(map, vUv);
                vec4 alphaMapColor = texture2D(alphaMap, vUv);

                if(hasMap && (mapColor.a * opacity)  < alphaTest){
                    discard;
                }

                if(hasAlphaMap && alphaMapColor.g < alphaTest){
                    discard;
                }
     
                gl_FragColor = vec4(1.0);
            }
        `,
        // blending: THREE.NoBlending, // 渲染时不与背景融合计算 直接替换
        depthTest: false,
        depthWrite: false,
        transparent: true
    });


    //拷贝纹理着色器
    static copyShader = new THREE.ShaderMaterial({
        ...CopyShader,
        depthTest: false,
        depthWrite: false,
        transparent: true
    });

    // 颜色设置 没有被遮挡的地方就是绿色 挡住了 就是红色
    static diffShader = new THREE.RawShaderMaterial({
        uniforms: {
            baseTexture: { value: null },
            selectTexture: { value: null },
            visibleColor: { value: new THREE.Color("#0f0") }, // 没有被挡住的地方的颜色绿色
            hiddenColor: { value: new THREE.Color("#ff0") },  // 被挡住的地方的颜色红色
            hiddenColorEnable: { value: true }                // 是否显示被挡住的地方
        },
        vertexShader: `
            attribute vec3 position;
            attribute vec2 uv;
            varying vec2 vUv;
            void main() {
                vUv = uv;
                gl_Position = vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            #ifdef GL_ES
                precision highp float;
            #endif
            uniform sampler2D baseTexture;
            uniform sampler2D selectTexture;
            uniform bool hiddenColorEnable;
            uniform vec3 visibleColor;
            uniform vec3 hiddenColor;
            varying vec2 vUv;

            void main() {

                vec4 selectColor = texture2D(selectTexture, vUv);

                gl_FragColor = vec4(0.0);

                if (length(selectColor.rgb) == 0.0) {
                    return;
                }

                vec4 baseColor = texture2D(baseTexture, vUv);

                if (selectColor.rgb == baseColor.rgb) {

                    gl_FragColor = vec4(visibleColor, 1.0);

                } else if (hiddenColorEnable){

                    gl_FragColor = vec4(hiddenColor, 1.0);
                }

            }
        `,
        blending: THREE.NoBlending, // 渲染时不与背景融合计算 直接替换
        depthTest: false,
        depthWrite: false,
        transparent: true
    });


    // 描边着色器
    static blurShader = new THREE.RawShaderMaterial({
        uniforms: {
            tDiffuse: { value: null },
            visibleColor: { value: new THREE.Color("#0f0") }, // 没有被挡住的地方的颜色绿色
            hiddenColor: { value: new THREE.Color("#f00") },  // 被挡住的地方的颜色红色
            width: { value: 1.0 },
            opacity: { value: 0.9 },
            resolution: { value: new THREE.Vector2(1 / 512, 1 / 512) }, // 渲染器的分辨率
            offset: {
                value: [
                    new THREE.Vector2(0.000, 1.000),
                    new THREE.Vector2(0.259, 0.966),
                    new THREE.Vector2(0.500, 0.866),
                    new THREE.Vector2(0.707, 0.707),
                    new THREE.Vector2(0.866, 0.500),
                    new THREE.Vector2(0.966, 0.259),
                    new THREE.Vector2(1.000, 0.000),
                    new THREE.Vector2(0.966, -0.259),
                    new THREE.Vector2(0.866, -0.500),
                    new THREE.Vector2(0.707, -0.707),
                    new THREE.Vector2(0.500, -0.866),
                    new THREE.Vector2(0.259, -0.966),
                    new THREE.Vector2(0.000, -1.000),
                    new THREE.Vector2(-0.259, -0.966),
                    new THREE.Vector2(-0.500, -0.866),
                    new THREE.Vector2(-0.707, -0.707),
                    new THREE.Vector2(-0.866, -0.500),
                    new THREE.Vector2(-0.966, -0.259),
                    new THREE.Vector2(-1.000, -0.000),
                    new THREE.Vector2(-0.966, 0.259),
                    new THREE.Vector2(-0.866, 0.500),
                    new THREE.Vector2(-0.707, 0.707),
                    new THREE.Vector2(-0.500, 0.866),
                    new THREE.Vector2(-0.259, 0.966)
                ]
            }
        },
        vertexShader: `
		attribute vec3 position;
		attribute vec2 uv;
		varying vec2 vUv;
		void main() {
			vUv = uv;
			gl_Position = vec4(position, 1.0);
		}`,
        fragmentShader: `
		#ifdef GL_ES
			precision highp float;
		#endif
		uniform sampler2D tDiffuse;
		uniform vec3 visibleColor;
		uniform vec3 hiddenColor;
		uniform float width;
		uniform float opacity;
		uniform vec2 resolution;
		uniform vec2 offset[24];
		varying vec2 vUv;
		vec2 piexl = resolution * width; // 描边厚度

		vec4 stroke(){
			vec4 blurColor = vec4(0.0);
			vec4 Color = vec4(0.0);
			int vSum = 0; // 周围像素点中和 visibleColor 相似的数量
			int hSum = 0; // 周围像素点中和 hiddenColor 相似的数量
			for (int i = 0; i < 24; i++ ) {
				Color = texture2D(tDiffuse, vUv + (offset[i] * piexl));
				if (Color.a > 0.0) {
					blurColor += Color;
					if(distance(blurColor.rgb, visibleColor) < distance(blurColor.rgb, hiddenColor)){
						vSum +=1;
					}else{
						hSum +=1;
					}
				}
			}
			if (blurColor.a < 0.001) {
				return vec4(0.0);
			} else if (vSum >= hSum) {
				return vec4(visibleColor, opacity);
			} else {
				return vec4(hiddenColor, opacity);
			}
		}
		void main() {
			vec4 color = texture2D(tDiffuse, vUv);
			if (color.a > 0.0 || width == 0.0) {
				gl_FragColor = color;
			} else {
				gl_FragColor = stroke();
			}
		}`,
        blending: THREE.NoBlending, // 渲染时不与背景融合计算 直接替换
        depthTest: false,
        depthWrite: false,
        transparent: true
    });

    // 高斯模糊着色器 让颜色过渡更自然
    static gaussBlurShader = new THREE.RawShaderMaterial({
        uniforms: {
            tDiffuse: { value: null },
            opacity: { value: 1.0 },
            resolution: { value: new THREE.Vector2(1 / 512, 1 / 512) }, // 渲染器的分辨率
        },
        vertexShader: `
		attribute vec3 position;
		attribute vec2 uv;
		varying vec2 vUv;
		void main() {
			vUv = uv;
			gl_Position = vec4(position, 1.0);
		}
	`,
        fragmentShader: `
		#ifdef GL_ES
			precision highp float;
		#endif
		uniform sampler2D tDiffuse;
		uniform float opacity;
		uniform vec2 resolution;
		varying vec2 vUv;

		vec2 piexl = resolution * 3.0; // 模糊厚度

		vec4 blur(){ // 套用高斯模糊公式
			vec4 blurColor = vec4(0.0);

			blurColor += (texture2D(tDiffuse, vUv + (vec2(-2.0, -2.0) * piexl)) * 1.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-2.0, -1.0) * piexl)) * 2.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-2.0, 0.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-2.0, 1.0) * piexl)) * 2.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-2.0, 2.0) * piexl)) * 1.0);

			blurColor += (texture2D(tDiffuse, vUv + (vec2(-1.0, -2.0) * piexl)) * 2.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-1.0, -1.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-1.0, 0.0) * piexl)) * 8.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-1.0, 1.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(-1.0, 2.0) * piexl)) * 2.0);

			blurColor += (texture2D(tDiffuse, vUv + (vec2(0.0, -2.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(0.0, -1.0) * piexl)) * 8.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(0.0, 0.0) * piexl)) * 16.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(0.0, 1.0) * piexl)) * 8.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(0.0, 2.0) * piexl)) * 4.0);

			blurColor += (texture2D(tDiffuse, vUv + (vec2(1.0, -2.0) * piexl)) * 2.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(1.0, -1.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(1.0, 0.0) * piexl)) * 8.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(1.0, 1.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(1.0, 2.0) * piexl)) * 2.0);

			blurColor += (texture2D(tDiffuse, vUv + (vec2(2.0, -2.0) * piexl)) * 1.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(2.0, -1.0) * piexl)) * 2.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(2.0, 0.0) * piexl)) * 4.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(2.0, 1.0) * piexl)) * 2.0);
			blurColor += (texture2D(tDiffuse, vUv + (vec2(2.0, 2.0) * piexl)) * 1.0);

			blurColor /= 100.0;

			return blurColor;
		}

		void main() {
			gl_FragColor = blur();
			gl_FragColor.a *=  opacity;
		}
	`,
        // blending: THREE.NoBlending, // 渲染时不与背景融合计算
        depthTest: false,
        depthWrite: false,
        transparent: true
    });

    // 最后辉光需要减去选中对象的发光效果 达到只显示边缘光的效果
    static filterSelectShader = new THREE.RawShaderMaterial({
        uniforms: {
            selectTexture: { value: null },
            blurTexture: { value: null }
        },
        vertexShader: `
		attribute vec3 position;
		attribute vec2 uv;
		varying vec2 vUv;
		void main() {
			vUv = uv;
			gl_Position = vec4(position, 1.0);
		}
	`,
        fragmentShader: `
		#ifdef GL_ES
			precision highp float;
		#endif
		uniform sampler2D selectTexture;
		uniform sampler2D blurTexture;
		varying vec2 vUv;

		void main() {
			gl_FragColor = texture2D(blurTexture, vUv);
			gl_FragColor.a -= (texture2D(selectTexture, vUv).a);
		}
	`,
        blending: THREE.NoBlending, // 渲染时不与背景融合计算 直接替换
        depthTest: false,
        depthWrite: false,
        transparent: true
    });

    // 模型材质
    static mesh_material = new THREE.MeshBasicMaterial();

    // 临时模型对象
    static meshTemp = (() => {
        const mesh = new THREE.Mesh();
        mesh.matrixAutoUpdate = false;
        mesh.material = new THREE.MeshBasicMaterial();
        return mesh;
    })();

    // 临时线模型对象
    static lineTemp = (() => {
        const line = new THREE.Line();
        line.matrixAutoUpdate = false;
        return line;
    })();

    // 临时线段模型对象
    static lineSegmentsTemp = (() => {
        const lineSegments = new THREE.LineSegments();
        lineSegments.matrixAutoUpdate = false;
        return lineSegments;
    })();

    // 临时线2模型对象
    static line2Temp = (() => {
        const line2 = new Line2();
        line2.matrixAutoUpdate = false;
        _.set(line2.material, ["defines", "USE_DASH"], true);
        _.set(line2.material, ["clipping"], true);
        return line2;
    })();

    // 临时线段模型对象
    static lineSegments2Temp = (() => {
        const lineSegments2 = new LineSegments2();
        lineSegments2.matrixAutoUpdate = false;
        _.set(lineSegments2.material, ["defines", "USE_DASH"], true);
        _.set(lineSegments2.material, ["clipping"], true);
        return lineSegments2;
    })();

    // 临时线段模型对象
    static pointsTemp = (() => {
        const points = new Points();
        points.matrixAutoUpdate = false;
        return points;
    })();

    //零时的实例模型对象
    static instanced_mesh_temp = (() => {
        const instanced_mesh = new THREEInstancedMesh(new THREE.BufferGeometry(), GlowPass.mesh_material);
        instanced_mesh.matrixAutoUpdate = false;
        return instanced_mesh;
    })();

    // 设置通道尺寸
    setSize(width: number, height: number) {

        const maxSide = Math.max(width, height);
        const scele = 512 / maxSide;
        width *= scele;
        height *= scele;

        GlowPass.baseTextureTarget.setSize(width, height);
        GlowPass.selectTextureTarget.setSize(width, height);
        GlowPass.diffTextureTarget.setSize(width, height);
        GlowPass.blur1TextureTarget.setSize(width, height);
        GlowPass.blur2TextureTarget.setSize(width, height);
        GlowPass.alphaMapTextureTarget.setSize(width, height);
        GlowPass.gaussBlurShader.uniforms.resolution.value.set(1 / width, 1 / height); // 设置高斯模糊着色器的分辨率
        GlowPass.blurShader.uniforms.resolution.value.set(1 / width, 1 / height); // 设置描边着色器的分辨率

    }

    // 渲染单个对象的颜色
    renderObject3d(
        renderer: WebGLRenderer,
        camera: Camera,
        object3d: Object3D,
        color?: string
    ) {

        // 空模型无需渲染
        if (!(object3d as any)["isTHREEInstancedMeshItem"] && _.isEmpty(_.get(object3d, ["geometry", "attributes", "position", "array"]))) {
            return;
        }

        if (!color) {
            return;
        }

        // 透明度小于可见肉眼可见的就忽略
        if (object3d.material.opacity < 0.1) {
            return;
        }

        if ((object3d as unknown as Line2)["isLine2"]) {

            GlowPass.line2Temp.geometry = (object3d as unknown as Line2).geometry;

            const { dashSize, gapSize, linewidth, clippingPlanes, clipIntersection, resolution, alphaToCoverage } = object3d.material as LineMaterial;

            Object.assign(GlowPass.line2Temp.material, {
                alphaToCoverage,
                dashSize,
                gapSize,
                linewidth,
                clippingPlanes,
                clipIntersection,
                needsUpdate: true
            });

            GlowPass.line2Temp.material.color.set(color);
            GlowPass.line2Temp.material.resolution.copy(resolution);
            GlowPass.line2Temp.matrixWorld.copy(object3d.matrixWorld);


            renderer.render(GlowPass.line2Temp, camera);

        } else if ((object3d as unknown as LineSegments2)["isLineSegments2"]) {

            GlowPass.lineSegments2Temp.geometry = (object3d as unknown as Line2).geometry;

            const { resolution, dashSize, gapSize, linewidth, clippingPlanes, clipIntersection } = object3d.material as LineMaterial;

            Object.assign(GlowPass.lineSegments2Temp.material, {
                dashSize,
                gapSize,
                linewidth,
                clippingPlanes,
                clipIntersection,
                needsUpdate: true
            });

            GlowPass.lineSegments2Temp.material.color.set(color);
            GlowPass.lineSegments2Temp.material.resolution.copy(resolution);
            GlowPass.lineSegments2Temp.matrixWorld.copy(object3d.matrixWorld);

            renderer.render(GlowPass.lineSegments2Temp, camera);


            //线条很细做深度测试意义不大
        } else if ((object3d as unknown as Line)["isLine"] || (object3d as unknown as LineSegments)["isLineSegments"]) {
            return;

        } else if ((object3d as unknown as Points)["isPoints"]) {

            GlowPass.pointsTemp.geometry = object3d.geometry;

            const { size, sizeAttenuation, map, alphaTest, alphaMap, opacity, side, clippingPlanes, clipIntersection, transparent } = object3d.material as PointsMaterial;

            const { renderOrder } = object3d;

            let originRenderTarget = renderer.getRenderTarget();

            // 把模型绘制到 透明通道纹理上面
            renderer.setRenderTarget(GlowPass.alphaMapTextureTarget);
            renderer.clear();
            GlowPass.fsQuad.material = GlowPass.alphaMapShader;
            GlowPass.alphaMapShader.uniforms.map.value = map;
            GlowPass.alphaMapShader.uniforms.hasMap.value = !!map;
            GlowPass.alphaMapShader.uniforms.alphaTest.value = 0.1;
            GlowPass.alphaMapShader.uniforms.alphaMap.value = alphaMap;
            GlowPass.alphaMapShader.uniforms.hasAlphaMap.value = !!alphaMap;
            GlowPass.alphaMapShader.uniforms.opacity.value = opacity;
            GlowPass.fsQuad.render(renderer);

            renderer.setRenderTarget(originRenderTarget);

            Object.assign(GlowPass.pointsTemp.material, {
                alphaTest,
                alphaMap: GlowPass.alphaMapTextureTarget.texture,
                opacity,
                side,
                size,
                clippingPlanes,
                clipIntersection,
                transparent,
                needsUpdate: true,
                sizeAttenuation
            });

            (GlowPass.pointsTemp.material as MeshBasicMaterial).color.set(color);
            GlowPass.pointsTemp.matrixWorld.copy(object3d.matrixWorld);
            GlowPass.pointsTemp.renderOrder = renderOrder;
            renderer.render(GlowPass.pointsTemp, camera);

        } else if ((object3d as any)["isTHREEInstancedMeshItem"]) {

            if ((object3d as unknown as THREEInstancedMeshItem).instancedMeshParent) {

                const { map, alphaTest, alphaMap, displacementMap, displacementScale, opacity, side, wireframe, clippingPlanes, clipIntersection, transparent } = (object3d as unknown as THREEInstancedMeshItem).instancedMeshParent!.material as MeshStandardMaterial;

                let originRenderTarget = renderer.getRenderTarget();

                // 把模型绘制到 透明通道纹理上面
                renderer.setRenderTarget(GlowPass.alphaMapTextureTarget);
                renderer.clear();
                GlowPass.fsQuad.material = GlowPass.alphaMapShader;
                GlowPass.alphaMapShader.uniforms.map.value = map;
                GlowPass.alphaMapShader.uniforms.hasMap.value = !!map;
                GlowPass.alphaMapShader.uniforms.alphaTest.value = 0.1;
                GlowPass.alphaMapShader.uniforms.alphaMap.value = alphaMap;
                GlowPass.alphaMapShader.uniforms.hasAlphaMap.value = !!alphaMap;
                GlowPass.alphaMapShader.uniforms.opacity.value = opacity;
                GlowPass.fsQuad.render(renderer);

                renderer.setRenderTarget(originRenderTarget);

                Object.assign(GlowPass.instanced_mesh_temp.material, {
                    alphaTest,
                    alphaMap: GlowPass.alphaMapTextureTarget.texture,
                    opacity,
                    side,
                    wireframe,
                    displacementMap,
                    displacementScale,
                    clippingPlanes,
                    clipIntersection,
                    transparent,
                    needsUpdate: true
                });

                const { renderOrder, geometry, matrixWorld } = (object3d as unknown as THREEInstancedMeshItem).instancedMeshParent!;

                GlowPass.instanced_mesh_temp.geometry = geometry;
                (GlowPass.instanced_mesh_temp.material as MeshBasicMaterial).color.set(color);
                GlowPass.instanced_mesh_temp.matrixWorld.copy(matrixWorld);
                GlowPass.instanced_mesh_temp.renderOrder = renderOrder;
                GlowPass.instanced_mesh_temp.setMatrixAt(0, object3d.matrixWorld);
                GlowPass.instanced_mesh_temp.instanceMatrix.needsUpdate = true;
                GlowPass.instanced_mesh_temp.count = 1;
                renderer.render(GlowPass.instanced_mesh_temp, camera);
            }

        } else if ((object3d as any)["isInstancedMesh"]) {

            GlowPass.instanced_mesh_temp.geometry = object3d.geometry;

            const { map, alphaTest, alphaMap, displacementMap, displacementScale, opacity, side, wireframe, clippingPlanes, clipIntersection, transparent } = object3d.material as MeshStandardMaterial;

            const { renderOrder } = object3d;

            let originRenderTarget = renderer.getRenderTarget();

            // 把模型绘制到 透明通道纹理上面
            renderer.setRenderTarget(GlowPass.alphaMapTextureTarget);
            renderer.clear();
            GlowPass.fsQuad.material = GlowPass.alphaMapShader;
            GlowPass.alphaMapShader.uniforms.map.value = map;
            GlowPass.alphaMapShader.uniforms.hasMap.value = !!map;
            GlowPass.alphaMapShader.uniforms.alphaTest.value = 0.1;
            GlowPass.alphaMapShader.uniforms.alphaMap.value = alphaMap;
            GlowPass.alphaMapShader.uniforms.hasAlphaMap.value = !!alphaMap;
            GlowPass.alphaMapShader.uniforms.opacity.value = opacity;
            GlowPass.fsQuad.render(renderer);

            renderer.setRenderTarget(originRenderTarget);

            Object.assign(GlowPass.instanced_mesh_temp.material, {
                alphaTest,
                alphaMap: GlowPass.alphaMapTextureTarget.texture,
                opacity,
                side,
                wireframe,
                displacementMap,
                displacementScale,
                clippingPlanes,
                clipIntersection,
                transparent,
                needsUpdate: true
            });

            (GlowPass.instanced_mesh_temp.material as MeshBasicMaterial).color.set(color);
            GlowPass.instanced_mesh_temp.matrixWorld.copy(object3d.matrixWorld);
            GlowPass.instanced_mesh_temp.renderOrder = renderOrder;
            GlowPass.instanced_mesh_temp.instanceMatrix = (object3d as unknown as THREEInstancedMesh).instanceMatrix;
            GlowPass.instanced_mesh_temp.count = (object3d as unknown as THREEInstancedMesh).count;
            renderer.render(GlowPass.instanced_mesh_temp, camera);

        } else if ((object3d as any)["isMesh"]) {

            GlowPass.meshTemp.geometry = object3d.geometry;

            const { map, alphaTest, alphaMap, displacementMap, displacementScale, opacity, side, wireframe, clippingPlanes, clipIntersection, transparent } = object3d.material as MeshStandardMaterial;

            const { renderOrder } = object3d;

            let originRenderTarget = renderer.getRenderTarget();

            // 把模型绘制到 透明通道纹理上面
            renderer.setRenderTarget(GlowPass.alphaMapTextureTarget);
            renderer.clear();
            GlowPass.fsQuad.material = GlowPass.alphaMapShader;
            GlowPass.alphaMapShader.uniforms.map.value = map;
            GlowPass.alphaMapShader.uniforms.hasMap.value = !!map;
            GlowPass.alphaMapShader.uniforms.alphaTest.value = 0.1;
            GlowPass.alphaMapShader.uniforms.alphaMap.value = alphaMap;
            GlowPass.alphaMapShader.uniforms.hasAlphaMap.value = !!alphaMap;
            GlowPass.alphaMapShader.uniforms.opacity.value = opacity;
            GlowPass.fsQuad.render(renderer);

            renderer.setRenderTarget(originRenderTarget);

            Object.assign(GlowPass.meshTemp.material, {
                alphaTest,
                alphaMap: GlowPass.alphaMapTextureTarget.texture,
                opacity,
                side,
                wireframe,
                displacementMap,
                displacementScale,
                clippingPlanes,
                clipIntersection,
                transparent,
                needsUpdate: true
            });

            (GlowPass.meshTemp.material as MeshBasicMaterial).color.set(color);
            GlowPass.meshTemp.matrixWorld.copy(object3d.matrixWorld);
            GlowPass.meshTemp.renderOrder = renderOrder;
            renderer.render(GlowPass.meshTemp, camera);
        }
    }

    // 获取动态的计算的透明度
    getOpacity() {
        if (this.glow_pulsePeriod > 0) {
            return this.glow_opacity * (Math.abs(((performance.now() / 1000) % (this.glow_pulsePeriod * 2)) - this.glow_pulsePeriod) / this.glow_pulsePeriod);

        } else {
            return this.glow_opacity;
        }
    }


    // 渲染辉光
    render(renderer: THREE.WebGLRenderer) {

        if (!this.object3d.visible) {
            // console.warn("glowPass: object3d.visible = false");
            return;
        }

        if (!this.glow_visibleColor) {
            // console.warn("glowPass: object3d.glow_visibleColor = undefind");
            return;
        }

        renderer.setRenderTarget(GlowPass.diffTextureTarget);
        renderer.clear();
        renderer.setRenderTarget(GlowPass.blur1TextureTarget);
        renderer.clear();
        renderer.setRenderTarget(GlowPass.blur2TextureTarget);
        renderer.clear();


        // 绘制其他对象
        if (this.glow_depthTest) {
            this.object3d.visible = false;
            renderer.setRenderTarget(GlowPass.baseTextureTarget);
            renderer.clear();
            this.scene.traverseVisible(obj => {
                this.renderObject3d(renderer, this.camera, obj as Object3D, this.glow_hiddenColor || "#000000");
            });
            this.object3d.visible = true;
            this.object3d.traverseVisible(obj => {
                this.renderObject3d(renderer, this.camera, obj as Object3D, this.glow_visibleColor);
            });
        }


        // 开启辉光深度测试就绘制到被选中对象的纹理中, 没有开启深度测试就直接绘制到比对结果纹理中去
        renderer.setRenderTarget(GlowPass.selectTextureTarget);
        renderer.clear();
        this.object3d.traverseVisible(obj => {
            this.renderObject3d(renderer, this.camera, obj as Object3D, this.glow_visibleColor);
        });

        // 开启辉光深度测试时比对纹理颜色计算
        if (this.glow_depthTest) {
            renderer.setRenderTarget(GlowPass.diffTextureTarget);
            renderer.clear();
            GlowPass.fsQuad.material = GlowPass.diffShader;
            GlowPass.diffShader.uniforms.baseTexture.value = GlowPass.baseTextureTarget.texture;
            GlowPass.diffShader.uniforms.selectTexture.value = GlowPass.selectTextureTarget.texture;
            GlowPass.diffShader.uniforms.visibleColor.value.set(this.glow_visibleColor); // 没有被挡住的地方的颜色
            GlowPass.diffShader.uniforms.hiddenColor.value.set(this.glow_hiddenColor || "#000000"); // 被挡住的地方的颜色
            GlowPass.diffShader.uniforms.hiddenColorEnable.value = !!this.glow_hiddenColor; // 是否显示被遮挡的辉光
            GlowPass.fsQuad.render(renderer);
        } else {
            renderer.setRenderTarget(GlowPass.diffTextureTarget);
            renderer.clear();
            GlowPass.fsQuad.material = GlowPass.copyShader;
            GlowPass.copyShader.uniforms.tDiffuse.value = GlowPass.selectTextureTarget.texture;
            GlowPass.fsQuad.render(renderer);
        }

        //比对完成开始绘制描边
        GlowPass.blurShader.uniforms.visibleColor.value.set(this.glow_visibleColor);
        GlowPass.blurShader.uniforms.hiddenColor.value.set(this.glow_depthTest ? this.glow_hiddenColor : this.glow_visibleColor);



        //一次描边
        renderer.setRenderTarget(GlowPass.blur1TextureTarget);
        GlowPass.blurShader.uniforms.tDiffuse.value = this.glow_depthTest ? GlowPass.diffTextureTarget.texture : GlowPass.selectTextureTarget.texture;
        GlowPass.blurShader.uniforms.width.value = this.glow_blurWidth / 4;
        GlowPass.blurShader.uniforms.opacity.value = 0.8;
        GlowPass.fsQuad.material = GlowPass.blurShader;
        GlowPass.fsQuad.render(renderer);



        //二次描边
        renderer.setRenderTarget(GlowPass.blur2TextureTarget);
        GlowPass.blurShader.uniforms.tDiffuse.value = GlowPass.blur1TextureTarget.texture;
        GlowPass.blurShader.uniforms.width.value = this.glow_blurWidth / 3;
        GlowPass.blurShader.uniforms.opacity.value = 0.4;
        GlowPass.fsQuad.material = GlowPass.blurShader;
        GlowPass.fsQuad.render(renderer);


        //三次描边
        renderer.setRenderTarget(GlowPass.blur1TextureTarget);
        GlowPass.blurShader.uniforms.tDiffuse.value = GlowPass.blur2TextureTarget.texture;
        GlowPass.blurShader.uniforms.width.value = this.glow_blurWidth / 2;
        GlowPass.blurShader.uniforms.opacity.value = 0.2;
        GlowPass.fsQuad.material = GlowPass.blurShader;
        GlowPass.fsQuad.render(renderer);

        //四次描边
        renderer.setRenderTarget(GlowPass.blur2TextureTarget);
        GlowPass.blurShader.uniforms.tDiffuse.value = GlowPass.blur1TextureTarget.texture;
        GlowPass.blurShader.uniforms.width.value = this.glow_blurWidth;
        GlowPass.blurShader.uniforms.opacity.value = 0.1;
        GlowPass.fsQuad.material = GlowPass.blurShader;
        GlowPass.fsQuad.render(renderer);

        //五次描边
        renderer.setRenderTarget(GlowPass.blur1TextureTarget);
        GlowPass.blurShader.uniforms.tDiffuse.value = GlowPass.blur2TextureTarget.texture;
        GlowPass.blurShader.uniforms.width.value = this.glow_blurWidth;
        GlowPass.blurShader.uniforms.opacity.value = 0.05;
        GlowPass.fsQuad.material = GlowPass.blurShader;
        GlowPass.fsQuad.render(renderer);



        // 只显示轮廓
        if (this.glow_fill === true) {

            // 把5次描边纹理进行高斯模糊处理 让渐变变得平滑 并存入 readBuffer 传递给后续通道
            renderer.setRenderTarget(null);
            GlowPass.gaussBlurShader.uniforms.tDiffuse.value = GlowPass.blur1TextureTarget.texture;
            GlowPass.gaussBlurShader.uniforms.opacity.value = this.getOpacity(); // 设置透明度
            GlowPass.gaussBlurShader.blending = THREE.NormalBlending; // 与有的纹理融合计算 保留前面通道传递下来的纹理
            GlowPass.fsQuad.material = GlowPass.gaussBlurShader;
            GlowPass.fsQuad.render(renderer);

        } else {

            // 把5次描边纹理进行高斯模糊处理 让渐变变得平滑 并存入 blur2TextureTarget
            renderer.setRenderTarget(GlowPass.blur2TextureTarget);
            GlowPass.fsQuad.material = GlowPass.gaussBlurShader;
            GlowPass.gaussBlurShader.uniforms.tDiffuse.value = GlowPass.blur1TextureTarget.texture;
            GlowPass.gaussBlurShader.uniforms.opacity.value = this.getOpacity(); // 设置透明度
            GlowPass.gaussBlurShader.blending = THREE.NoBlending; // 与有的纹理融合计算 保留前面通道传递下来的纹理
            GlowPass.fsQuad.render(renderer);


            renderer.setRenderTarget(null);
            GlowPass.fsQuad.material = GlowPass.filterSelectShader;
            GlowPass.filterSelectShader.uniforms.selectTexture.value = GlowPass.selectTextureTarget.texture;
            GlowPass.filterSelectShader.uniforms.blurTexture.value = GlowPass.blur2TextureTarget.texture;
            GlowPass.filterSelectShader.blending = THREE.NormalBlending; // 与有的纹理融合计算 保留前面通道传递下来的纹理
            GlowPass.fsQuad.render(renderer);

        } // 显示轮廓

        // 调试代码
        // renderer.setRenderTarget(null);
        // GlowPass.copyShader.uniforms.tDiffuse.value = GlowPass.blur2TextureTarget.texture;
        // GlowPass.copyShader.blending = 1;
        // GlowPass.fsQuad.material = GlowPass.copyShader;
        // GlowPass.fsQuad.render(renderer);
        // return;


        // renderer.setRenderTarget(null);
    }



}
